package org.quincy.rock.core.dao.sql;

import java.util.HashMap;
import java.util.Map;

import org.apache.commons.lang3.mutable.MutableInt;
import org.quincy.rock.core.dao.DaoUtil;

/**
 * <b>OpExpression。</b>
 * <p><b>详细说明：</b></p>
 * <!-- 在此添加详细说明 -->
 * 无。
 * 
 * @version 1.0
 * @author wks
 * @since 1.0
 */
@SuppressWarnings("unchecked")
public abstract class OpExpression extends AbstractExpression {
	/**
	 * serialVersionUID。
	 */
	private static final long serialVersionUID = 6609510101484441673L;

	/**
	 * 关系操作符
	 */
	private Op op;

	private Map<String, Object> sqlParameter;
	private String prefix;
	private String open;
	private String close;

	public Op op() {
		return op;
	}

	public <T extends OpExpression> T op(Op op) {
		this.op = op;
		return (T) this;
	}

	public String getOp() {
		return op().op();
	}

	public void setOp(String op) {
		this.op = Op.of(op);
	}

	public Map<String, Object> getSqlParameter() {
		if (sqlParameter == null)
			sqlParameter = new HashMap<>();
		return sqlParameter;
	}

	public String prefix() {
		return prefix == null ? "where" : prefix;
	}

	public <T extends OpExpression> T prefix(String prefix) {
		this.prefix = prefix;
		return (T) this;
	}

	public String open() {
		return open == null ? "#{" : open;
	}

	public <T extends OpExpression> T open(String open) {
		this.open = open;
		return (T) this;
	}

	public String close() {
		return close == null ? "}" : close;
	}

	public <T extends OpExpression> T close(String close) {
		this.close = close;
		return (T) this;
	}

	@Override
	public String getSqlFragment() {
		Map<String, Object> sqlParameter = getSqlParameter();
		MutableInt index = new MutableInt(0);
		String baseName = prefix() + ".sqlParameter.";
		return build(new StringBuilder(), nameInterceptor(), (v, dt, match) -> {
			String varName = "_sp_" + index.incrementAndGet();
			if (match != null)
				v = DaoUtil.likeString(v.toString(), match);
			sqlParameter.put(varName, v);
			return new StringBuilder(open()).append(baseName).append(varName).append(close());
		}).toString();
	}
}
